home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / Miro_Downloader.exe / email / _parseaddr.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-11-12  |  12.9 KB  |  544 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''Email address parsing code.
  5.  
  6. Lifted directly from rfc822.py.  This should eventually be rewritten.
  7. '''
  8. __all__ = [
  9.     'mktime_tz',
  10.     'parsedate',
  11.     'parsedate_tz',
  12.     'quote']
  13. import time
  14. SPACE = ' '
  15. EMPTYSTRING = ''
  16. COMMASPACE = ', '
  17. _monthnames = [
  18.     'jan',
  19.     'feb',
  20.     'mar',
  21.     'apr',
  22.     'may',
  23.     'jun',
  24.     'jul',
  25.     'aug',
  26.     'sep',
  27.     'oct',
  28.     'nov',
  29.     'dec',
  30.     'january',
  31.     'february',
  32.     'march',
  33.     'april',
  34.     'may',
  35.     'june',
  36.     'july',
  37.     'august',
  38.     'september',
  39.     'october',
  40.     'november',
  41.     'december']
  42. _daynames = [
  43.     'mon',
  44.     'tue',
  45.     'wed',
  46.     'thu',
  47.     'fri',
  48.     'sat',
  49.     'sun']
  50. _timezones = {
  51.     'UT': 0,
  52.     'UTC': 0,
  53.     'GMT': 0,
  54.     'Z': 0,
  55.     'AST': -400,
  56.     'ADT': -300,
  57.     'EST': -500,
  58.     'EDT': -400,
  59.     'CST': -600,
  60.     'CDT': -500,
  61.     'MST': -700,
  62.     'MDT': -600,
  63.     'PST': -800,
  64.     'PDT': -700 }
  65.  
  66. def parsedate_tz(data):
  67.     '''Convert a date string to a time tuple.
  68.  
  69.     Accounts for military timezones.
  70.     '''
  71.     data = data.split()
  72.     if data[0].endswith(',') or data[0].lower() in _daynames:
  73.         del data[0]
  74.     else:
  75.         i = data[0].rfind(',')
  76.         if i >= 0:
  77.             data[0] = data[0][i + 1:]
  78.         
  79.     if len(data) == 3:
  80.         stuff = data[0].split('-')
  81.         if len(stuff) == 3:
  82.             data = stuff + data[1:]
  83.         
  84.     
  85.     if len(data) == 4:
  86.         s = data[3]
  87.         i = s.find('+')
  88.         if i > 0:
  89.             data[3:] = [
  90.                 s[:i],
  91.                 s[i + 1:]]
  92.         else:
  93.             data.append('')
  94.     
  95.     if len(data) < 5:
  96.         return None
  97.     
  98.     data = data[:5]
  99.     (dd, mm, yy, tm, tz) = data
  100.     mm = mm.lower()
  101.     if mm not in _monthnames:
  102.         dd = mm
  103.         mm = dd.lower()
  104.         if mm not in _monthnames:
  105.             return None
  106.         
  107.     
  108.     mm = _monthnames.index(mm) + 1
  109.     if mm > 12:
  110.         mm -= 12
  111.     
  112.     if dd[-1] == ',':
  113.         dd = dd[:-1]
  114.     
  115.     i = yy.find(':')
  116.     if i > 0:
  117.         yy = tm
  118.         tm = yy
  119.     
  120.     if yy[-1] == ',':
  121.         yy = yy[:-1]
  122.     
  123.     if not yy[0].isdigit():
  124.         yy = tz
  125.         tz = yy
  126.     
  127.     if tm[-1] == ',':
  128.         tm = tm[:-1]
  129.     
  130.     tm = tm.split(':')
  131.     if len(tm) == 2:
  132.         (thh, tmm) = tm
  133.         tss = '0'
  134.     elif len(tm) == 3:
  135.         (thh, tmm, tss) = tm
  136.     else:
  137.         return None
  138.     
  139.     try:
  140.         yy = int(yy)
  141.         dd = int(dd)
  142.         thh = int(thh)
  143.         tmm = int(tmm)
  144.         tss = int(tss)
  145.     except ValueError:
  146.         return None
  147.  
  148.     tzoffset = None
  149.     tz = tz.upper()
  150.     if _timezones.has_key(tz):
  151.         tzoffset = _timezones[tz]
  152.     else:
  153.         
  154.         try:
  155.             tzoffset = int(tz)
  156.         except ValueError:
  157.             pass
  158.  
  159.     if tzoffset:
  160.         if tzoffset < 0:
  161.             tzsign = -1
  162.             tzoffset = -tzoffset
  163.         else:
  164.             tzsign = 1
  165.         tzoffset = tzsign * ((tzoffset // 100) * 3600 + (tzoffset % 100) * 60)
  166.     
  167.     return (yy, mm, dd, thh, tmm, tss, 0, 1, -1, tzoffset)
  168.  
  169.  
  170. def parsedate(data):
  171.     '''Convert a time string to a time tuple.'''
  172.     t = parsedate_tz(data)
  173.     if isinstance(t, tuple):
  174.         return t[:9]
  175.     else:
  176.         return t
  177.  
  178.  
  179. def mktime_tz(data):
  180.     '''Turn a 10-tuple as returned by parsedate_tz() into a UTC timestamp.'''
  181.     if data[9] is None:
  182.         return time.mktime(data[:8] + (-1,))
  183.     else:
  184.         t = time.mktime(data[:8] + (0,))
  185.         return t - data[9] - time.timezone
  186.  
  187.  
  188. def quote(str):
  189.     '''Add quotes around a string.'''
  190.     return str.replace('\\', '\\\\').replace('"', '\\"')
  191.  
  192.  
  193. class AddrlistClass:
  194.     '''Address parser class by Ben Escoto.
  195.  
  196.     To understand what this class does, it helps to have a copy of RFC 2822 in
  197.     front of you.
  198.  
  199.     Note: this class interface is deprecated and may be removed in the future.
  200.     Use rfc822.AddressList instead.
  201.     '''
  202.     
  203.     def __init__(self, field):
  204.         """Initialize a new instance.
  205.  
  206.         `field' is an unparsed address header field, containing
  207.         one or more addresses.
  208.         """
  209.         self.specials = '()<>@,:;."[]'
  210.         self.pos = 0
  211.         self.LWS = ' \t'
  212.         self.CR = '\r\n'
  213.         self.atomends = self.specials + self.LWS + self.CR
  214.         self.phraseends = self.atomends.replace('.', '')
  215.         self.field = field
  216.         self.commentlist = []
  217.  
  218.     
  219.     def gotonext(self):
  220.         '''Parse up to the start of the next address.'''
  221.         while self.pos < len(self.field):
  222.             if self.field[self.pos] in self.LWS + '\n\r':
  223.                 self.pos += 1
  224.                 continue
  225.             self
  226.             if self.field[self.pos] == '(':
  227.                 self.commentlist.append(self.getcomment())
  228.                 continue
  229.             break
  230.  
  231.     
  232.     def getaddrlist(self):
  233.         '''Parse all addresses.
  234.  
  235.         Returns a list containing all of the addresses.
  236.         '''
  237.         result = []
  238.         while self.pos < len(self.field):
  239.             ad = self.getaddress()
  240.             if ad:
  241.                 result += ad
  242.                 continue
  243.             result.append(('', ''))
  244.         return result
  245.  
  246.     
  247.     def getaddress(self):
  248.         '''Parse the next address.'''
  249.         self.commentlist = []
  250.         self.gotonext()
  251.         oldpos = self.pos
  252.         oldcl = self.commentlist
  253.         plist = self.getphraselist()
  254.         self.gotonext()
  255.         returnlist = []
  256.         if self.pos >= len(self.field):
  257.             if plist:
  258.                 returnlist = [
  259.                     (SPACE.join(self.commentlist), plist[0])]
  260.             
  261.         elif self.field[self.pos] in '.@':
  262.             self.pos = oldpos
  263.             self.commentlist = oldcl
  264.             addrspec = self.getaddrspec()
  265.             returnlist = [
  266.                 (SPACE.join(self.commentlist), addrspec)]
  267.         elif self.field[self.pos] == ':':
  268.             returnlist = []
  269.             fieldlen = len(self.field)
  270.             self.pos += 1
  271.             while self.pos < len(self.field):
  272.                 self.gotonext()
  273.                 returnlist = returnlist + self.getaddress()
  274.                 continue
  275.                 None if self.pos < fieldlen and self.field[self.pos] == ';' else self
  276.         elif self.field[self.pos] == '<':
  277.             routeaddr = self.getrouteaddr()
  278.             if self.commentlist:
  279.                 returnlist = [
  280.                     (SPACE.join(plist) + ' (' + ' '.join(self.commentlist) + ')', routeaddr)]
  281.             else:
  282.                 returnlist = [
  283.                     (SPACE.join(plist), routeaddr)]
  284.         elif plist:
  285.             returnlist = [
  286.                 (SPACE.join(self.commentlist), plist[0])]
  287.         elif self.field[self.pos] in self.specials:
  288.             self.pos += 1
  289.         
  290.         self.gotonext()
  291.         if self.pos < len(self.field) and self.field[self.pos] == ',':
  292.             self.pos += 1
  293.         
  294.         return returnlist
  295.  
  296.     
  297.     def getrouteaddr(self):
  298.         '''Parse a route address (Return-path value).
  299.  
  300.         This method just skips all the route stuff and returns the addrspec.
  301.         '''
  302.         if self.field[self.pos] != '<':
  303.             return None
  304.         
  305.         expectroute = False
  306.         self.pos += 1
  307.         self.gotonext()
  308.         adlist = ''
  309.         while self.pos < len(self.field):
  310.             if expectroute:
  311.                 self.getdomain()
  312.                 expectroute = False
  313.             elif self.field[self.pos] == '>':
  314.                 self.pos += 1
  315.                 break
  316.             elif self.field[self.pos] == '@':
  317.                 self.pos += 1
  318.                 expectroute = True
  319.             elif self.field[self.pos] == ':':
  320.                 self.pos += 1
  321.             else:
  322.                 adlist = self.getaddrspec()
  323.                 self.pos += 1
  324.                 break
  325.             self.gotonext()
  326.             continue
  327.             self
  328.         return adlist
  329.  
  330.     
  331.     def getaddrspec(self):
  332.         '''Parse an RFC 2822 addr-spec.'''
  333.         aslist = []
  334.         self.gotonext()
  335.         while self.pos < len(self.field):
  336.             if self.field[self.pos] == '.':
  337.                 aslist.append('.')
  338.                 self.pos += 1
  339.             elif self.field[self.pos] == '"':
  340.                 aslist.append('"%s"' % self.getquote())
  341.             elif self.field[self.pos] in self.atomends:
  342.                 break
  343.             else:
  344.                 aslist.append(self.getatom())
  345.             self.gotonext()
  346.         if self.pos >= len(self.field) or self.field[self.pos] != '@':
  347.             return EMPTYSTRING.join(aslist)
  348.         
  349.         aslist.append('@')
  350.         self.pos += 1
  351.         self.gotonext()
  352.         return EMPTYSTRING.join(aslist) + self.getdomain()
  353.  
  354.     
  355.     def getdomain(self):
  356.         '''Get the complete domain name from an address.'''
  357.         sdlist = []
  358.         while self.pos < len(self.field):
  359.             if self.field[self.pos] in self.LWS:
  360.                 self.pos += 1
  361.                 continue
  362.             self
  363.             if self.field[self.pos] == '(':
  364.                 self.commentlist.append(self.getcomment())
  365.                 continue
  366.             if self.field[self.pos] == '[':
  367.                 sdlist.append(self.getdomainliteral())
  368.                 continue
  369.             if self.field[self.pos] == '.':
  370.                 self.pos += 1
  371.                 sdlist.append('.')
  372.                 continue
  373.             self
  374.             if self.field[self.pos] in self.atomends:
  375.                 break
  376.                 continue
  377.             sdlist.append(self.getatom())
  378.         return EMPTYSTRING.join(sdlist)
  379.  
  380.     
  381.     def getdelimited(self, beginchar, endchars, allowcomments = True):
  382.         """Parse a header fragment delimited by special characters.
  383.  
  384.         `beginchar' is the start character for the fragment.
  385.         If self is not looking at an instance of `beginchar' then
  386.         getdelimited returns the empty string.
  387.  
  388.         `endchars' is a sequence of allowable end-delimiting characters.
  389.         Parsing stops when one of these is encountered.
  390.  
  391.         If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed
  392.         within the parsed fragment.
  393.         """
  394.         if self.field[self.pos] != beginchar:
  395.             return ''
  396.         
  397.         slist = [
  398.             '']
  399.         quote = False
  400.         self.pos += 1
  401.         while self.pos < len(self.field):
  402.             if quote:
  403.                 slist.append(self.field[self.pos])
  404.                 quote = False
  405.             elif self.field[self.pos] in endchars:
  406.                 self.pos += 1
  407.                 break
  408.             elif allowcomments and self.field[self.pos] == '(':
  409.                 slist.append(self.getcomment())
  410.                 continue
  411.             elif self.field[self.pos] == '\\':
  412.                 quote = True
  413.             else:
  414.                 slist.append(self.field[self.pos])
  415.             self.pos += 1
  416.             continue
  417.             self
  418.         return EMPTYSTRING.join(slist)
  419.  
  420.     
  421.     def getquote(self):
  422.         """Get a quote-delimited fragment from self's field."""
  423.         return self.getdelimited('"', '"\r', False)
  424.  
  425.     
  426.     def getcomment(self):
  427.         """Get a parenthesis-delimited fragment from self's field."""
  428.         return self.getdelimited('(', ')\r', True)
  429.  
  430.     
  431.     def getdomainliteral(self):
  432.         '''Parse an RFC 2822 domain-literal.'''
  433.         return '[%s]' % self.getdelimited('[', ']\r', False)
  434.  
  435.     
  436.     def getatom(self, atomends = None):
  437.         """Parse an RFC 2822 atom.
  438.  
  439.         Optional atomends specifies a different set of end token delimiters
  440.         (the default is to use self.atomends).  This is used e.g. in
  441.         getphraselist() since phrase endings must not include the `.' (which
  442.         is legal in phrases)."""
  443.         atomlist = [
  444.             '']
  445.         if atomends is None:
  446.             atomends = self.atomends
  447.         
  448.         while self.pos < len(self.field):
  449.             if self.field[self.pos] in atomends:
  450.                 break
  451.             else:
  452.                 atomlist.append(self.field[self.pos])
  453.             self.pos += 1
  454.             continue
  455.             self
  456.         return EMPTYSTRING.join(atomlist)
  457.  
  458.     
  459.     def getphraselist(self):
  460.         '''Parse a sequence of RFC 2822 phrases.
  461.  
  462.         A phrase is a sequence of words, which are in turn either RFC 2822
  463.         atoms or quoted-strings.  Phrases are canonicalized by squeezing all
  464.         runs of continuous whitespace into one space.
  465.         '''
  466.         plist = []
  467.         while self.pos < len(self.field):
  468.             if self.field[self.pos] in self.LWS:
  469.                 self.pos += 1
  470.                 continue
  471.             self
  472.             if self.field[self.pos] == '"':
  473.                 plist.append(self.getquote())
  474.                 continue
  475.             if self.field[self.pos] == '(':
  476.                 self.commentlist.append(self.getcomment())
  477.                 continue
  478.             if self.field[self.pos] in self.phraseends:
  479.                 break
  480.                 continue
  481.             plist.append(self.getatom(self.phraseends))
  482.         return plist
  483.  
  484.  
  485.  
  486. class AddressList(AddrlistClass):
  487.     '''An AddressList encapsulates a list of parsed RFC 2822 addresses.'''
  488.     
  489.     def __init__(self, field):
  490.         AddrlistClass.__init__(self, field)
  491.         if field:
  492.             self.addresslist = self.getaddrlist()
  493.         else:
  494.             self.addresslist = []
  495.  
  496.     
  497.     def __len__(self):
  498.         return len(self.addresslist)
  499.  
  500.     
  501.     def __add__(self, other):
  502.         newaddr = AddressList(None)
  503.         newaddr.addresslist = self.addresslist[:]
  504.         for x in other.addresslist:
  505.             if x not in self.addresslist:
  506.                 newaddr.addresslist.append(x)
  507.                 continue
  508.         
  509.         return newaddr
  510.  
  511.     
  512.     def __iadd__(self, other):
  513.         for x in other.addresslist:
  514.             if x not in self.addresslist:
  515.                 self.addresslist.append(x)
  516.                 continue
  517.         
  518.         return self
  519.  
  520.     
  521.     def __sub__(self, other):
  522.         newaddr = AddressList(None)
  523.         for x in self.addresslist:
  524.             if x not in other.addresslist:
  525.                 newaddr.addresslist.append(x)
  526.                 continue
  527.         
  528.         return newaddr
  529.  
  530.     
  531.     def __isub__(self, other):
  532.         for x in other.addresslist:
  533.             if x in self.addresslist:
  534.                 self.addresslist.remove(x)
  535.                 continue
  536.         
  537.         return self
  538.  
  539.     
  540.     def __getitem__(self, index):
  541.         return self.addresslist[index]
  542.  
  543.  
  544.